using System.Collections.Immutable;
using System.Diagnostics;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

public class AnalysisCategory : AnalysisExpression
{
    private readonly AnalysisIdentifier?[] _children = [null, null];

    public AnalysisCategory(CategoryLiteral source, AnalysisCategorical parent) :
        base(AnalysisBoundKinds.Category, source, parent)
    {
        if (source.RangeLeft != null)
        {
            _children[0] = AnalysisNodeFactory.Identifier(source.RangeLeft, this, null);
        }

        if (source.RangeRight != null)
        {
            _children[1] = AnalysisNodeFactory.Identifier(source.RangeRight, this, null);
        }

        if (source.IntegerValue != null)
        {
            Value = AnalysisNodeFactory.Integer(source.IntegerValue, this);
        }
    }


    public AnalysisIdentifier? RangeLeft => _children[0];

    public AnalysisIdentifier? RangeRight => _children[1];

    public bool IsRange => ((CategoryLiteral)Syntax).DotDotToken != null;

    public AnalysisInteger? Value { get; }


    public override int ChildrenCount => 2;


    public override IEnumerable<AnalysisNode> GetChildren()
    {
        return _children.ToImmutableArray();
    }

    internal override void AddChild(AnalysisNode child)
    {
        Debug.Assert(child.Syntax.IsNode(SyntaxKinds.Identifier));

        if (_children[0] == null)
        {
            _children[0] = (AnalysisIdentifier)child;
        }
        else if (_children[1] == null)
        {
            _children[1] = (AnalysisIdentifier)child;
        }
        else
        {
            throw new NotSupportedException("AnalysisCategory already has left boundary and right boundary.");
        }

        child.Parent = this;
    }

    public override AnalysisNode? AcceptVisitor(AnalysisTreeVisitor visitor)
    {
        AnalysisNode? result;

        if (RangeLeft != null && (result = visitor.Visit(RangeLeft)) != null)
        {
            return result;
        }

        if (RangeRight != null && (result = visitor.Visit(RangeRight)) != null)
        {
            return result;
        }

        if (Value != null && (result = visitor.Visit(Value)) != null)
        {
            return result;
        }

        return null;
    }
}
